{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# A Model of the Fed's View on Inflation\n",
    "\n",
    "### Thomas Hasenzagl$^1$, Filippo Pellegrino$^2$, Lucrezia Reichlin$^3$, Giovanni Ricco$^4$\n",
    "\n",
    "$^1$ University of Minnesota <br>\n",
    "$^2$ London School of Economics and Political Science <br>\n",
    "$^3$ London Business School, Now-Casting Economics, and CEPR <br>\n",
    "$^4$ University of Warwick and OFCE-SciencesPo <br>\n",
    "\n",
    "\n",
    "#### Notebook description\n",
    "\n",
    "This notebook generates the charts and tables from the out-of-sample estimation exercise from the paper \"A Model of the Fed's View on Inflation\". Before running this notebook you have to run `user_main.jl` using `run_type=3`. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<script>\n",
       "// Immediately-invoked-function-expression to avoid global variables.\n",
       "(function() {\n",
       "    var warning_div = document.getElementById(\"webio-warning-16158092445422237131\");\n",
       "    var hide = function () {\n",
       "        var script = document.getElementById(\"webio-setup-3053571156729510321\");\n",
       "        var parent = script && script.parentElement;\n",
       "        var grandparent = parent && parent.parentElement;\n",
       "        if (grandparent) {\n",
       "            grandparent.style.display = \"none\";\n",
       "        }\n",
       "        warning_div.style.display = \"none\";\n",
       "    };\n",
       "    if (typeof Jupyter !== \"undefined\") {\n",
       "        console.log(\"WebIO detected Jupyter notebook environment.\");\n",
       "        // Jupyter notebook.\n",
       "        var extensions = (\n",
       "            Jupyter\n",
       "            && Jupyter.notebook.config.data\n",
       "            && Jupyter.notebook.config.data.load_extensions\n",
       "        );\n",
       "        if (extensions && extensions[\"webio-jupyter-notebook\"]) {\n",
       "            // Extension already loaded.\n",
       "            console.log(\"Jupyter WebIO nbextension detected; not loading ad-hoc.\");\n",
       "            hide();\n",
       "            return;\n",
       "        }\n",
       "    } else if (window.location.pathname.includes(\"/lab\")) {\n",
       "        // Guessing JupyterLa\n",
       "        console.log(\"Jupyter Lab detected; make sure the @webio/jupyter-lab-provider labextension is installed.\");\n",
       "        hide();\n",
       "        return;\n",
       "    }\n",
       "})();\n",
       "\n",
       "</script>\n",
       "<p\n",
       "    id=\"webio-warning-16158092445422237131\"\n",
       "    class=\"output_text output_stderr\"\n",
       "    style=\"padding: 1em; font-weight: bold;\"\n",
       ">\n",
       "    Unable to load WebIO. Please make sure WebIO works for your Jupyter client.\n",
       "    For troubleshooting, please see <a href=\"https://juliagizmos.github.io/WebIO.jl/latest/providers/ijulia/\">\n",
       "    the WebIO/IJulia documentation</a>.\n",
       "    <!-- TODO: link to installation docs. -->\n",
       "</p>\n"
      ],
      "text/plain": [
       "HTML{String}(\"<script>\\n// Immediately-invoked-function-expression to avoid global variables.\\n(function() {\\n    var warning_div = document.getElementById(\\\"webio-warning-16158092445422237131\\\");\\n    var hide = function () {\\n        var script = document.getElementById(\\\"webio-setup-3053571156729510321\\\");\\n        var parent = script && script.parentElement;\\n        var grandparent = parent && parent.parentElement;\\n        if (grandparent) {\\n            grandparent.style.display = \\\"none\\\";\\n        }\\n        warning_div.style.display = \\\"none\\\";\\n    };\\n    if (typeof Jupyter !== \\\"undefined\\\") {\\n        console.log(\\\"WebIO detected Jupyter notebook environment.\\\");\\n        // Jupyter notebook.\\n        var extensions = (\\n            Jupyter\\n            && Jupyter.notebook.config.data\\n            && Jupyter.notebook.config.data.load_extensions\\n        );\\n        if (extensions && extensions[\\\"webio-jupyter-notebook\\\"]) {\\n            // Extension already loaded.\\n            console.log(\\\"Jupyter WebIO nbextension detected; not loading ad-hoc.\\\");\\n            hide();\\n            return;\\n        }\\n    } else if (window.location.pathname.includes(\\\"/lab\\\")) {\\n        // Guessing JupyterLa\\n        console.log(\\\"Jupyter Lab detected; make sure the @webio/jupyter-lab-provider labextension is installed.\\\");\\n        hide();\\n        return;\\n    }\\n})();\\n\\n</script>\\n<p\\n    id=\\\"webio-warning-16158092445422237131\\\"\\n    class=\\\"output_text output_stderr\\\"\\n    style=\\\"padding: 1em; font-weight: bold;\\\"\\n>\\n    Unable to load WebIO. Please make sure WebIO works for your Jupyter client.\\n    For troubleshooting, please see <a href=\\\"https://juliagizmos.github.io/WebIO.jl/latest/providers/ijulia/\\\">\\n    the WebIO/IJulia documentation</a>.\\n    <!-- TODO: link to installation docs. -->\\n</p>\\n\")"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# ----- Load libraries -----\n",
    "\n",
    "using CSV, JLD;\n",
    "using Dates, DataFrames, Statistics;\n",
    "include(\"MetropolisWithinGibbs.jl\");\n",
    "using Main.MetropolisWithinGibbs;\n",
    "using PlotlyJS, ORCA;\n",
    "pltjs = PlotlyJS;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# User input\n",
    "titles = [\"Real GDP\", \"Employment\", \"Unemployment rate\", \"Oil price\", \"CPI inflation\", \"Core CPI inflation\", \"UOM: Expected inflation\", \"SPF: Expected inflation\"];\n",
    "scales = [\"Bil. Chn. 2009\\$\", \"Thousands\", \"Percent\", \"\\$/Barrel\", \"Percent\", \"Percent\", \"Percent\", \"Percent\"];"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load chunk0\n",
    "res_chunk0 = load(\"res_oos_chunk0.jld\");\n",
    "\n",
    "# Load information about the out-of-sample period\n",
    "data          = res_chunk0[\"data_full\"];\n",
    "date          = res_chunk0[\"date\"];\n",
    "MNEMONIC      = res_chunk0[\"MNEMONIC\"];\n",
    "end_presample = res_chunk0[\"end_presample\"];\n",
    "end_oos       = res_chunk0[\"end_oos\"];\n",
    "oos_length    = res_chunk0[\"oos_length\"];"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Reading chunk 1 (out of 31)\n",
      "Reading chunk 10 (out of 31)\n",
      "Reading chunk 20 (out of 31)\n",
      "Reading chunk 30 (out of 31)\n",
      "Reading chunk 31 (out of 31)\n"
     ]
    }
   ],
   "source": [
    "# Initialise oos_forecast, α_array and σ_array\n",
    "oos_forecast = Array{Any}(undef, oos_length);\n",
    "α_array      = Array{Any}(undef, oos_length);\n",
    "σ_array      = Array{Any}(undef, oos_length);\n",
    "\n",
    "# Loop over every out-of-sample period\n",
    "for i=1:oos_length\n",
    "    \n",
    "    # Info\n",
    "    if i == 1 || mod(i, 10) == 0 || i == oos_length\n",
    "        println(\"Reading chunk $(i) (out of $(oos_length))\");\n",
    "    end\n",
    "    \n",
    "    # Load i-th chunk\n",
    "    res = jldopen(\"res_oos_chunk$(i).jld\", \"r\");\n",
    "    \n",
    "    # Update oos_forecast, α_array and σ_array\n",
    "    oos_forecast[i] = read(res[\"distr_fcst\"]);\n",
    "    α_array[i] = read(res[\"distr_α\"]);\n",
    "    σ_array[i] = read(res[\"σʸ\"]);\n",
    "end\n",
    "\n",
    "# Forecast horizon\n",
    "max_h = size(oos_forecast[1])[1];"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialise point forecasts, random walk forecasts\n",
    "point_forecast = zeros(oos_length-max_h, size(data,2), max_h) |> Array{Union{Missing, Float64}};\n",
    "rw_forecast    = zeros(oos_length-max_h, size(data,2), max_h) |> Array{Union{Missing, Float64}};\n",
    "actual         = zeros(oos_length-max_h, size(data,2), max_h) |> Array{Union{Missing, Float64}};"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Point forecast and random walk\n",
    "for i=1:oos_length-max_h\n",
    "    \n",
    "    # Drift\n",
    "    d = mean(diff(data[1:end_presample+i-1,:], dims=1), dims=1)[:];\n",
    "\n",
    "    # Loop over the forecast horizon\n",
    "    for hz = 1:max_h\n",
    "        \n",
    "        # Random walk benchmark\n",
    "        if hz == 1\n",
    "            rw_forecast[i, :, hz] = d .+ data[end_presample+i-1, :];\n",
    "        else\n",
    "            rw_forecast[i, :, hz] = d .+ rw_forecast[i, :, hz-1]\n",
    "        end\n",
    "        \n",
    "        # Median forecast\n",
    "        point_forecast[i, :, hz] = median(oos_forecast[i][hz, :, :], dims=2);\n",
    "        \n",
    "        # Actual data\n",
    "        actual[i, :, hz] = data[end_presample+i+hz-1, :];\n",
    "    end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Compute RMSFE\n",
    "tc_rmsfe = sqrt.(dropdims(mean((actual - point_forecast).^2, dims=1), dims=1));\n",
    "rw_rmsfe = sqrt.(dropdims(mean((actual - rw_forecast).^2, dims=1), dims=1));\n",
    "\n",
    "# RMSFE DataFrame\n",
    "df_rmsfe = DataFrame(tc_rmsfe./rw_rmsfe);\n",
    "rename!(df_rmsfe, Symbol.([\"h$(hz)\" for hz=1:max_h]))\n",
    "CSV.write(\"rmsfe.csv\", df_rmsfe);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Stability of the common components"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "figures = Array{Any}(undef, 3);\n",
    "\n",
    "c1 = \"rgba(0, 48, 158, .75)\"; \n",
    "c2 = \"rgba(255, 0, 0, .75)\";\n",
    "\n",
    "titles_sub = [\"Business Cycle\", \"Energy Price Cycle\", \"Common Trend\"]\n",
    "scales_sub = [\"\", \"\", \"\"];\n",
    "\n",
    "for i=1:3\n",
    "        \n",
    "    traces1 = Array{Any}(undef, length(α_array));\n",
    "\n",
    "    for j=1:length(α_array)\n",
    "        \n",
    "        if i==1\n",
    "            αij = median(α_array[j][1,:,:], dims=2);\n",
    "        elseif i==2\n",
    "            αij = median(α_array[j][4,:,:], dims=2);\n",
    "        elseif i==3\n",
    "            αij = median(α_array[j][6,:,:], dims=2);\n",
    "        end\n",
    "        \n",
    "        traces1[j] = pltjs.scatter(x=date[1:end-max_h], y=αij[1:end-max_h], name=\"State\", mode=\"lines\", line=attr(width=1), showlegend=false);\n",
    "    end\n",
    "    \n",
    "    traces1 = convert(Array{PlotlyJS.GenericTrace{Dict{Symbol,Any}},1}, traces1)\n",
    "\n",
    "    layout  = pltjs.Layout(;title=titles_sub[i], titlefont=attr(size=12),\n",
    "                           xaxis=attr(tickfont_size=10, showgrid=true, linecolor=\"black\", mirror=true, nticks=20, tickangle=-90, zeroline=false),\n",
    "                           yaxis=attr(tickfont_size=10, showgrid=true, linecolor=\"black\", mirror=true, zeroline=false, titlefont=attr(size=10), title=scales_sub[i]));\n",
    "\n",
    "    figures[i] = pltjs.plot(traces1, layout);\n",
    "end\n",
    "\n",
    "fig = [figures[1]; figures[2]; figures[3]];\n",
    "\n",
    "# Size\n",
    "fig.plot.layout[\"width\"]  = 800;\n",
    "fig.plot.layout[\"height\"] = 600;\n",
    "\n",
    "# Margins\n",
    "fig.plot.layout[\"margin\"][:b]  = 40;\n",
    "fig.plot.layout[\"margin\"][:t]  = 40;\n",
    "fig.plot.layout[\"margin\"][:r]  = 40;\n",
    "fig.plot.layout[\"margin\"][:l]  = 40;\n",
    "\n",
    "# Title size\n",
    "for i=1:3\n",
    "    fig.plot.layout[\"annotations\"][i][:font][:size] = 12;\n",
    "end\n",
    "\n",
    "savefig(fig, \"factor_revisions.pdf\", format=\"pdf\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Julia 1.0.5",
   "language": "julia",
   "name": "julia-1.0"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "1.0.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
